package com.ayf.payment.game.api.httpclient;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.bean.BaseResData;
import com.ayf.payment.game.api.config.RequestConfig;
import com.ayf.payment.game.api.dto.MerchantDTO;
import com.ayf.payment.game.api.exception.AuthorizeFailedException;
import com.ayf.payment.game.api.exception.InvalidRequestException;
import com.ayf.payment.game.api.exception.InvalidResponseException;
import com.ayf.payment.game.api.type.CharSetEnum;
import com.ayf.payment.game.api.utils.CharSetUtil;
import com.ayf.payment.game.api.utils.CommonResult;
import com.ayf.payment.game.api.utils.JsonUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * httpclient工具类
 */
public class HttpUtils implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final String HEADER_KEY_NONCE = "nonce";
    private static final String HEADER_KEY_TIMESTAMP = "timestamp";
    private static final String HEADER_KEY_AUTHORIZATION = "Authorization";
    public static final String RESPONSE_CODE = "code";
    public static final String RESPONSE_DATA = "data";


    public static final String SUCCESS_CODE="SUCCESS";
    public static final String FAIL_CODE="FAIL";
    public static final String PROCESSING_CODE="PROCESSING";

    /**
     * 非空验证
     *
     * @param dto
     * @throws AuthorizeFailedException
     * @throws InvalidRequestException
     * @throws InvalidResponseException
     */
    private static void isNotBlank(MerchantDTO dto) throws AuthorizeFailedException, InvalidRequestException, InvalidResponseException {
//        if (StringUtils.isBlank(dto.getMerchantSecretKey())) {
//            throw new AuthorizeFailedException("Secret key can not be blank.Please set your Secret key in com.HttpUtil.config.SignConfig");
//        }
        if (StringUtils.isBlank(dto.getPrivateKey())) {
            throw new AuthorizeFailedException("RSA Private key can not be blank.Please set your RSA Private key  in com.HttpUtil.config.SignConfig");
        }
        if (StringUtils.isBlank(dto.getPublicKey())) {
            throw new InvalidRequestException("HttpUtil Public key can not be blank.Please set your HttpUtil Public key in com.HttpUtil.config.SignConfig");
        }
    }

    /**
     * 免签post请求
     * @param traceId
     * @param url
     * @param jsonReqData
     * @param socketTimeoutSecond
     * @return
     * @throws InvalidResponseException
     * @throws IOException
     */
    public static Map<String, String> noSignPost(String traceId,String url, String jsonReqData,int socketTimeoutSecond) throws InvalidResponseException, IOException {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json; charset=" + RequestConfig.CHARSET);
        httpPost.setEntity(new ByteArrayEntity(jsonReqData.getBytes(Charset.forName(RequestConfig.CHARSET)), ContentType.APPLICATION_JSON));
        Map<String, String> result = null;
        long time_start = System.currentTimeMillis();
        LogPortal.info("{} 调用请求开始 url:{} 请求参数:{}",traceId,url,jsonReqData);
        if (socketTimeoutSecond==0) {
            socketTimeoutSecond = 60;
        }
        org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                setConnectTimeout(3 * 1000).
                setConnectionRequestTimeout(3 * 1000).
                setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                build();
        CloseableHttpClient httpClient;
        try {
            httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
        } catch (NoSuchAlgorithmException e) {
            throw new IOException(e);
        } catch (KeyManagementException e) {
            throw new IOException(e);
        }
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            try {
                if (entity != null) {
                    int responseCode = response.getStatusLine().getStatusCode();
                    String resData = EntityUtils.toString(entity,Charset.forName(RequestConfig.CHARSET));
                    LogPortal.info("{} 调用请求响应 url:{}，耗时:{}ms，responseCode={}，resData={}", traceId, url, (System.currentTimeMillis() - time_start), responseCode, resData);
                    result = new HashMap<>();
                    result.put(RESPONSE_CODE, String.valueOf(responseCode));
                    result.put(RESPONSE_DATA,resData);
                }
            } catch (Exception e) {
                LogPortal.error("{} 调用请求响应失败 url:{} 发生了{}异常，错误描述:{}", traceId,url,e.getClass().getName(),e.getMessage());
            } finally {
                EntityUtils.consumeQuietly(entity);
            }
        }finally {
            httpPost.releaseConnection();
        }
        return result;
    }

    /**
     * 免签post请求 默认超时等待1分钟
     * @param traceId
     * @param url
     * @param jsonReqData
     * @return
     * @throws InvalidResponseException
     * @throws IOException
     */
    public static Map<String, String> noSignPost(String traceId,String url, String jsonReqData) throws InvalidResponseException, IOException {
        return noSignPost(traceId,url,jsonReqData,0);
    }

    /**
     * POST请求
     *
     * @param url
     * @param jsonReqData
     * @return
     * @throws IOException
     * @throws InvalidResponseException
     */
    public static Map<String, String> doPost(String traceId, String url, String jsonReqData, MerchantDTO dto, int socketTimeoutSecond) throws IOException, InvalidResponseException, AuthorizeFailedException {
        isNotBlank(dto);
        HttpPost httpPost = new HttpPost(url);
        setCustomHeaders(httpPost, dto);
        httpPost.setEntity(new ByteArrayEntity(jsonReqData.getBytes(Charset.forName(RequestConfig.CHARSET)), ContentType.APPLICATION_JSON));
        Map<String, String> result = null;
        String sign = signData(httpPost, dto);
        httpPost.addHeader(RequestConfig.SIGN, sign);
        long time_start = System.currentTimeMillis();
        //LogPortal.info("{} 调用请求开始 url:{} 请求参数:{}",traceId,url,jsonReqData);
        if (socketTimeoutSecond==0) {
            socketTimeoutSecond = 60;
        }
        org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                setConnectTimeout(3 * 1000).
                setConnectionRequestTimeout(3 * 1000).
                setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                build();
        CloseableHttpClient httpClient;
        try {
            httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
        } catch (NoSuchAlgorithmException e) {
            throw new IOException(e);
        } catch (KeyManagementException e) {
            throw new IOException(e);
        }
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            result = verifyData(traceId, response,url,time_start,dto);
        }finally {
            httpPost.releaseConnection();
        }
        return result;
    }
    public static Map<String, String> doPost2(String traceId, String url, String jsonReqData, MerchantDTO dto, int socketTimeoutSecond) throws IOException, InvalidResponseException, AuthorizeFailedException {
        isNotBlank(dto);
        HttpPost httpPost = new HttpPost(url);
        setCustomHeaders(httpPost, dto);
        httpPost.setEntity(new ByteArrayEntity(jsonReqData.getBytes(Charset.forName(RequestConfig.CHARSET)), ContentType.APPLICATION_JSON));
        Map<String, String> result = null;
        String sign = signData(httpPost, dto);
        httpPost.addHeader(RequestConfig.SIGN, sign);
        long time_start = System.currentTimeMillis();
        //LogPortal.info("{} 调用请求开始 url:{} 请求参数:{}",traceId,url,jsonReqData);
        if (socketTimeoutSecond==0) {
            socketTimeoutSecond = 60;
        }
        org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                setConnectTimeout(3 * 1000).
                setConnectionRequestTimeout(3 * 1000).
                setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                build();
        CloseableHttpClient httpClient;
        try {
            httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
        } catch (NoSuchAlgorithmException e) {
            throw new IOException(e);
        } catch (KeyManagementException e) {
            throw new IOException(e);
        }
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            result = verifyData2(traceId, response,url,time_start,dto);
        }finally {
            httpPost.releaseConnection();
        }
        return result;
    }

    /**
     * POST请求 默认超时等待1分钟
     * @param traceId
     * @param url
     * @param jsonReqData
     * @param dto
     * @return
     * @throws IOException
     * @throws InvalidResponseException
     * @throws AuthorizeFailedException
     */
    public static Map<String, String> doPost(String traceId, String url, String jsonReqData, MerchantDTO dto) throws IOException, InvalidResponseException, AuthorizeFailedException {
        return doPost(traceId,url,jsonReqData,dto,0);
    }
    public static Map<String, String> doPost2(String traceId, String url, String jsonReqData, MerchantDTO dto) throws IOException, InvalidResponseException, AuthorizeFailedException {
        return doPost2(traceId,url,jsonReqData,dto,0);
    }

    /**
     * 对返回结果进行验签。
     * 验签成功:返回数据
     * 验签失败:抛出异常
     *
     * @param response
     * @return
     * @throws IOException
     * @throws InvalidResponseException
     */
    private static Map<String, String> verifyData(String traceId, CloseableHttpResponse response, String url, long time_start, MerchantDTO dto) throws IOException, InvalidResponseException {
        Map<String, String> result = null;
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            try {
                int responseCode = response.getStatusLine().getStatusCode();
                String resData = EntityUtils.toString(entity, Charset.forName(RequestConfig.CHARSET));
                LogPortal.info("{} 调用请求响应 url:{}，耗时:{}ms，responseCode={}，resData={}", traceId, url, (System.currentTimeMillis() - time_start), responseCode, resData);
                String[] split = resData.split("\\|");
                if (split.length != 2) {
                    throw new InvalidResponseException("Response format error");
                }
                String signResData = split[0];
                String sign = split[1];
                if (responseCode == 200) {
                    String nonce = response.getFirstHeader(HEADER_KEY_NONCE) != null ? response.getFirstHeader(HEADER_KEY_NONCE).getValue() : "";
                    String timestamp = response.getFirstHeader(HEADER_KEY_TIMESTAMP) != null ? response.getFirstHeader(HEADER_KEY_TIMESTAMP).getValue() : "";
                    String secretKey = response.getFirstHeader(HEADER_KEY_AUTHORIZATION) != null ? response.getFirstHeader(HEADER_KEY_AUTHORIZATION).getValue() : "";
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    out.write(nonce.getBytes(RequestConfig.CHARSET));
                    out.write('\n');//header
                    out.write(timestamp.getBytes(RequestConfig.CHARSET));
                    out.write('\n');//header
                    out.write(secretKey.getBytes(RequestConfig.CHARSET));
                    out.write('\n');//header
                    byte[] data = signResData.getBytes(RequestConfig.CHARSET);
                    out.write(data);//body
                    out.close();
                    String toVerifyData = out.toString();
                    boolean flag = RSA.verify(toVerifyData, sign, dto.getPublicKey());
                    if (!flag) {
                        throw new InvalidResponseException("Invalid Response.[Response Data And Sign Verify Failure.]");
                    }
                    if (!dto.getMerchantSecretKey().equals(secretKey)) {
                        throw new InvalidResponseException("Invalid Response.[Secret Key Is Invalid.]");
                    }
                }
                result = new HashMap<>();
                result.put(RESPONSE_CODE, String.valueOf(responseCode));
                result.put(RESPONSE_DATA, signResData);
            } finally {
                EntityUtils.consumeQuietly(entity);
            }
        }
        return result;
    }
    private static Map<String, String> verifyData2(String traceId, CloseableHttpResponse response, String url, long time_start, MerchantDTO dto) throws IOException, InvalidResponseException {
        Map<String, String> result = null;
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            try {
                int responseCode = response.getStatusLine().getStatusCode();
                String resData = EntityUtils.toString(entity, Charset.forName(RequestConfig.CHARSET));
                LogPortal.info("{} 调用请求响应 url:{}，耗时:{}ms，responseCode={}，resData={}",traceId,url,(System.currentTimeMillis()-time_start),responseCode,resData);
                if (responseCode ==200) {
                    String nonce = response.getFirstHeader(HEADER_KEY_NONCE) != null ? response.getFirstHeader(HEADER_KEY_NONCE).getValue() : "";
                    String timestamp = response.getFirstHeader(HEADER_KEY_TIMESTAMP) != null ? response.getFirstHeader(HEADER_KEY_TIMESTAMP).getValue() : "";
                    String secretKey = response.getFirstHeader(HEADER_KEY_AUTHORIZATION) != null ? response.getFirstHeader(HEADER_KEY_AUTHORIZATION).getValue() : "";
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    out.write(nonce.getBytes(RequestConfig.CHARSET));
                    out.write('\n');//header
                    out.write(timestamp.getBytes(RequestConfig.CHARSET));
                    out.write('\n');//header
                    out.write(secretKey.getBytes(RequestConfig.CHARSET));
                    out.write('\n');//header
                    byte[] data = resData.getBytes(RequestConfig.CHARSET);
                    out.write(data);//body
                    out.close();
                    String toVerifyData = out.toString();
                    String sign = response.getFirstHeader(RequestConfig.SIGN) != null ? response.getFirstHeader(RequestConfig.SIGN).getValue() : "";
                    boolean flag = RSA.verify(toVerifyData, sign, dto.getPublicKey());
                    if (!flag) {
                        throw new InvalidResponseException("Invalid Response.[Response Data And Sign Verify Failure.]");
                    }
                    if (!dto.getMerchantSecretKey().equals(secretKey)) {
                        throw new InvalidResponseException("Invalid Response.[Secret Key Is Invalid.]");
                    }
                }
                result = new HashMap<>();
                result.put(RESPONSE_CODE, String.valueOf(responseCode));
                result.put(RESPONSE_DATA, resData);
            } finally {
                EntityUtils.consumeQuietly(entity);
            }
        }
        return result;
    }

    /**
     * 设置header
     *
     * @param request
     */
    private static void setCustomHeaders(HttpRequestBase request, MerchantDTO dto) {
        request.addHeader("Content-Type", "application/json; charset=" + RequestConfig.CHARSET);
        request.addHeader(HEADER_KEY_AUTHORIZATION, dto.getMerchantSecretKey());
        String timestamp = String.valueOf(System.currentTimeMillis());
        request.addHeader(HEADER_KEY_TIMESTAMP, timestamp);
        request.addHeader(HEADER_KEY_NONCE, UUID.randomUUID().toString().replaceAll("-", ""));
        String[] propertyNames = {"os.name", "os.version", "os.arch", "java.version", "java.vendor", "java.vm.version", "java.vm.vendor"};
        Map<String, String> propertyMap = new HashMap<>(10);
        for (String propertyName : propertyNames) {
            propertyMap.put(propertyName, System.getProperty(propertyName));
        }
        propertyMap.put("lang", "Java");
        propertyMap.put("publisher", "HttpUtils");
        propertyMap.put("sdk-version", RequestConfig.SDK_VERSION);
        request.addHeader("X-HttpUtil-Client-User-Agent", JSON.toJSONString(propertyMap));
    }

    /**
     * 签名方法
     *
     * @param httpRequest
     * @return
     * @throws IOException
     */
    private static String signData(HttpRequestBase httpRequest, MerchantDTO dto) throws IOException {
        Request<HttpRequest> request = new HttpRequestWrapper(httpRequest);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write(request.getMethod().toLowerCase().getBytes(RequestConfig.CHARSET));
        out.write('\n');//method
        String queryString = StringUtils.isBlank(request.getRequestQueryString()) ? "" : request.getRequestQueryString();
        out.write(queryString.getBytes(RequestConfig.CHARSET));
        out.write('\n');//query string
        out.write(request.getHeaderValue(HEADER_KEY_NONCE).getBytes(RequestConfig.CHARSET));
        out.write('\n');//header
        out.write(request.getHeaderValue(HEADER_KEY_TIMESTAMP).getBytes(RequestConfig.CHARSET));
        out.write('\n');//header
        out.write(request.getHeaderValue(HEADER_KEY_AUTHORIZATION).getBytes(RequestConfig.CHARSET));
        out.write('\n');//header
        byte[] data = IOUtils.toByteArray(request.getRequestBody());
        out.write(data);//body
        out.close();
        String toSignString = out.toString();
        String url = request.getRequestUriPath();
        //LogPortal.info("请求URL:{} 待签名字符串:{}", url, toSignString);
        LogPortal.info("dto.getPrivateKey():{}", dto.getPrivateKey());
        String sign = RSA.sign(toSignString, dto.getPrivateKey());
        LogPortal.info("请求URL:{} 生成的签名:{}", url, sign);
        return sign;
    }

    public static void main(String[] args) {
        String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCtNVrjqokupxi+Yh9YFF/64lWhpeHswiefg7stXN5jIrAfToCqmORp547x5qbF6PRRIX7+DFTmEeyhnALA3lwmJ/X2vv4CGi2CaTGxFtrd7BFVZOQq7Sb4goasapdu0jp43DrdZWWq5IZfz4+6NnQJLb35ARjGWiD2EG/+HJ/ABTHMG/AtracZWnVxOH8qoDXTGCsYWf3GicMdQQ6rJVUecfjuaYh+DmvOO6y3GmLjcNhZQRNDmrvgCWY/vZSfJZr3HWX0quDHbdhHtf6qx8tmoSwVBrsPKymWom8EmtCfvCOUd57usozA/6XuyfRCSvh9u8Ca75Eu6oppdtsIV05LAgMBAAECggEABKAGG0o0e5BusrbAC4QPxA1DKBvb2oycrj/AQcfXEGKevVdFTEjk4IcUZBU6otJDo973GyWNJs+XuAEIecn2P/aVNM+IzNmSGYdhkk7/7SkelV8qUJMglUY2/meiP41RjmSjFcJdYqDTjb9nIRvPIWedSQbkeHdzpd5ufySYh3IQtTtZJw2EufKe/4EXBob1zScdfNG1GwoA+XyDYxeWciNgt8Krwt2RyigOwFt9kwc6RwkNt7uEFZnvoy7GpwkQxrn7f/lnmbVIGFEsGyse6Owu1wgViPTGMKIRAKxXJB5R9ANTtsvPK4PgXlPq27Mo6Uimf2DRDQNdsOtK9aCfoQKBgQDyKqGm/yonan6+/Vllbnm6s0uEokCRAPozLGq+ZXk2AS4SdQ4y/3x4SMTpnaI2SA6bvnzVQCLz3U14fVaP9P9XRGFMXMl2oWyIsIlzmA2BBXcFLF63m/0Hm52/ZYhjB38IUuS6Jugvux+WAPrFpeObRUiJ7LBKbZzB2FuCfQHwOQKBgQC3Gk0sc3Zdh7/Hsi0jvQe2f+vcmL2RhsnIMGZsaq+zMhBIUagOwotrOSAHNTpzoD15a8KrUf04fLu/XpM4ejWBdg++BlcXMB24GOPscxjHmAIavFfEGjF51rOycFtOOPBxOTHMxYUHZfppIiNE5wHAoUE3QvlJ/4+CTtd8sEIqowKBgQCwxyAkSQabqWkGwOjeW4wvFy1ckBj0ATOj4Zu2i1q1ap0YSizoW4qgP/bG1xSP7YAEf0SfY2dgf79K4qwrAFzZdohUdzN2DxasnbppEKli8vtUYnRuMke+owG/sz2hlNpN2D0yCq7aEQ5YsTRezd9d/HCchpSWcHfLJcZ/dgPROQKBgQCJLrZ1QEiFSKiB6FdzeDOoIu1GiFU3C+JwDvsd7UyYGEEkvbEI5e7otZLuc43IhVypdPgTvUjXonRTq3rnjIA774VZ3IwxfkY14MgbJhyBpbyl5UhoTyuUWiyl2xI9Z+GVIsHR5oaFhXz4ebAs9lpUxTwEODRnoYYWnhVKgRABuwKBgQCYXDKjBoYIWiwRe4Fc1syCprBg/NpX+YlVzBBUu8K0Kx6wZHBq9NMfcnKaMhwvlTx+XYs6Tm8g96gyy6OJeqjNQh1GtZjzwaywFGCiIpaFRKCjrvhcIzrT+UDInjcOaOOSkZ9XwyS4r5F7VzRG5lINZQ/5fuZXcx5YNaWmX5wLig==";
        String sign = RSA.sign("123456789a123456789", privateKey);
        System.out.println(sign);
    }


    private static SSLContext getSslContext() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }}, new SecureRandom());
        return sslContext;
    }

    /**
     * GET请求
     *
     * @param traceId
     * @param url
     * @return
     */
    public static Map<String, String> doGet(String traceId, String url) throws IOException {
        Map<String, String> result = null;
        LogPortal.info("{} 调用请求开始 url:{}", traceId, url);
        long time_start = System.currentTimeMillis();
        //1、获取HttpClient对象
        CloseableHttpClient client = HttpClients.createDefault();
        //2、创建连接的方式
        HttpGet get = new HttpGet(url);
        //3、设置请求方式连接的参数
        get.setConfig(MyRequestConfig.getRequestConfig());
        CloseableHttpResponse response = null;
        //4、执行请求,获取服务器返回的结果
        response = client.execute(get);
        int responseCode = response.getStatusLine().getStatusCode();
        String resData = EntityUtils.toString(response.getEntity(), "utf-8");
        LogPortal.info("{} 调用请求响应 url:{}，耗时:{}ms，responseCode={}，resData={}", traceId, url, (System.currentTimeMillis() - time_start), responseCode, resData);
        result = new HashMap<>();
        result.put(RESPONSE_CODE, String.valueOf(responseCode));
        result.put(RESPONSE_DATA, resData);
        // 关闭连接
        response.close();
        client.close();
        return result;
    }

    public static Map<String, String> smsHttpPost(String traceId, String url, Map<String, String> params) throws IOException {
        Map<String, String> result = null;
        // 发送请求到公众平台
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> nvps = new ArrayList<>();
            for (String key : params.keySet()) {
                nvps.add(new BasicNameValuePair(key, params.get(key)));
            }

            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            int responseCode = response.getStatusLine().getStatusCode();
            String responseStr = EntityUtils.toString(entity, "utf-8");
            LogPortal.info("[{}] response body is [{}]", traceId, responseStr);
            result = new HashMap<>();
            result.put(RESPONSE_CODE, String.valueOf(responseCode));
            result.put(RESPONSE_DATA, responseStr);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                LogPortal.error("[{}] close response exception.", e, traceId);
            }
        }
        return result;
    }

    public static BaseResData sendGet(String traceId,String methodDesc,String url,Map<String, String> paramMap){
        return sendGet(traceId,methodDesc,url,paramMap,0);
    }


    public static BaseResData sendGet(String traceId,String methodDesc,String url,Map<String, String> paramMap,int socketTimeoutSecond) {
        //声明返回结果
        String result = "";
        //开始请求API接口时间
        long startTime=System.currentTimeMillis();
        //请求API接口的响应时间
        long endTime= 0L;
        int responseCode=-1;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = null;
        HttpEntity httpEntity = null;
        BaseResData baseResData = new BaseResData();
        try {
            // 设置链接超时等待时间
            if (socketTimeoutSecond ==0) { // 默认为2分钟
                socketTimeoutSecond = 120;
            }
            org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                    setConnectTimeout(10 * 1000).
                    setConnectionRequestTimeout(10 * 1000).
                    setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                    build();
            // 创建连接
            if (url.startsWith("https")){
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
            } else {
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
            }
            Charset charset = Charset.forName("UTF-8");
            URIBuilder uriBuilder = new URIBuilder(url);
            if (paramMap != null && paramMap.size()>0){
                Iterator iterator = paramMap.entrySet().iterator();
                while(iterator.hasNext()){
                    Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
                    uriBuilder.setParameter(elem.getKey(),elem.getValue());
                }
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Content-Type", "application/json;charset=UTF-8");

            LogPortal.info("{} {}请求开始 URL:{} 请求参数:{}",traceId,methodDesc,url,paramMap);
            response = httpClient.execute(httpGet);
            responseCode = response.getStatusLine().getStatusCode();
            if (responseCode ==200){
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    baseResData.setData(result);
                }
                if (StringUtils.isEmpty(result)){
                    baseResData.setRespMsg("响应报文内容为空");
                } else {
                    baseResData.setSuccess(true);
                }
            } else {
                baseResData.setRespMsg("HttpStatus非200，当前是:"+responseCode);
            }
        } catch (ConnectTimeoutException e) {
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        } catch (SocketTimeoutException e) {
            baseResData.setProcessing(true);
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        }catch (SocketException e) {
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        } catch (Exception e) {
            baseResData.setRespMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        } finally {
            try {
                if (httpEntity != null){
                    EntityUtils.consume(httpEntity);
                }
            } catch (IOException e) {
                LogPortal.error("{} {}http请求释放资源异常",e,traceId,methodDesc);
            }
        }
        //请求接口的响应时间
        endTime=System.currentTimeMillis();
        LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,result);
        return baseResData;
    }

    public static BaseResData sendPostForm(String traceId,String methodDesc,String url,Map<String, String> paramMap){
        return sendPostForm(traceId,methodDesc,url,paramMap,0,CharSetEnum.utf8);
    }

    public static BaseResData sendPostForm(String traceId,String methodDesc,String url,Map<String, String> paramMap,CharSetEnum charSetEnum){
        return sendPostForm(traceId,methodDesc,url,paramMap,0,charSetEnum);
    }

    public static CommonResult sendPostFormAyb(String traceId, String methodDesc, String url, Map<String, String> paramMap, CharSetEnum charSetEnum){
        return sendPostFormAyb(traceId,methodDesc,url,paramMap,0,charSetEnum);
    }

    public static BaseResData sendPostJson(String traceId, String methodDesc, String url, Map<String, String> paramMap){
        return sendPostJson(traceId,methodDesc,url,paramMap,0,CharSetEnum.utf8);
    }

    public static BaseResData sendPostForm(String traceId, String methodDesc, String url, Map<String, String> paramMap, int socketTimeoutSecond, CharSetEnum charSetEnum) {
        //声明返回结果
        String result = "";
        //开始请求API接口时间
        long startTime=System.currentTimeMillis();
        //请求API接口的响应时间
        long endTime= 0L;
        int responseCode=-1;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = null;
        HttpEntity httpEntity = null;
        BaseResData baseResData = new BaseResData();
        try {
            // 设置链接超时等待时间
            if (socketTimeoutSecond ==0) { // 默认为2分钟
                socketTimeoutSecond = 120;
            }
            org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                    setConnectTimeout(10 * 1000).
                    setConnectionRequestTimeout(10 * 1000).
                    setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                    build();
            // 创建连接
            if (url.startsWith("https")){
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
            } else {
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
            }
            Charset charset = Charset.forName(CharSetUtil.getCharSet(charSetEnum));
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> nvps = new ArrayList<>();
            for (String key : paramMap.keySet()) {
                nvps.add(new BasicNameValuePair(key, paramMap.get(key)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps,charset));

            LogPortal.info("{} {}请求开始 URL:{} 请求参数:{}",traceId,methodDesc,url,JSON.toJSONString(paramMap));
            response = httpClient.execute(httpPost);
            responseCode = response.getStatusLine().getStatusCode();
            if (responseCode ==200){
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    baseResData.setData(result);
                }
                if (StringUtils.isEmpty(result)){
                    baseResData.setRespMsg("响应报文内容为空");
                } else {
                    baseResData.setSuccess(true);
                }
            } else {
                baseResData.setRespMsg("HttpStatus非200，当前是:"+responseCode);
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    baseResData.setData(result);
                }
            }
        } catch (ConnectTimeoutException e) {
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        } catch (SocketTimeoutException e) {
            baseResData.setProcessing(true);
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        }catch (SocketException e) {
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        } catch (Exception e) {
            baseResData.setRespMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        } finally {
            try {
                if (httpEntity != null){
                    EntityUtils.consume(httpEntity);
                }
            } catch (IOException e) {
                LogPortal.error("{} {}http请求释放资源异常",e,traceId,methodDesc);
            }
        }
        //请求接口的响应时间
        endTime=System.currentTimeMillis();
        if ("互娱下单".equals(methodDesc)){
            if (StringUtils.isNotEmpty(result)){
                try {
                    JSONObject jsonObject =JSONObject.parseObject(result);
                    if ("5".equals(jsonObject.getString("datatype"))){
                        jsonObject.remove("data");
                    }
                    LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,jsonObject.toJSONString());
                } catch (Exception e) { }
            } else {
                LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,result);
            }
        } else {
            LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,result);
        }
        return baseResData;
    }

    public static BaseResData sendPostJson(String traceId, String methodDesc, String url, Map<String, String> paramMap, int socketTimeoutSecond, CharSetEnum charSetEnum) {
        //声明返回结果
        String result = "";
        //开始请求API接口时间
        long startTime=System.currentTimeMillis();
        //请求API接口的响应时间
        long endTime= 0L;
        int responseCode=-1;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = null;
        HttpEntity httpEntity = null;
        BaseResData baseResData = new BaseResData();
        try {
            // 设置链接超时等待时间
            if (socketTimeoutSecond ==0) { // 默认为2分钟
                socketTimeoutSecond = 120;
            }
            org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                    setConnectTimeout(10 * 1000).
                    setConnectionRequestTimeout(10 * 1000).
                    setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                    build();
            // 创建连接
            if (url.startsWith("https")){
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
            } else {
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
            }
            Charset charset = Charset.forName(CharSetUtil.getCharSet(charSetEnum));
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            String jsonParam = JSON.toJSONString(paramMap);
            StringEntity stringEntity = new StringEntity(jsonParam, "UTF-8");
            httpPost.setEntity(stringEntity);
            LogPortal.info("{} {}请求开始 URL:{} 请求参数:{}",traceId,methodDesc,url,jsonParam);
            response = httpClient.execute(httpPost);
            responseCode = response.getStatusLine().getStatusCode();
            if (responseCode ==200){
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    baseResData.setData(result);
                }
                if (StringUtils.isEmpty(result)){
                    baseResData.setRespMsg("响应报文内容为空");
                } else {
                    baseResData.setSuccess(true);
                }
            } else {
                baseResData.setRespMsg("HttpStatus非200，当前是:"+responseCode);
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    baseResData.setData(result);
                }
            }
        } catch (ConnectTimeoutException e) {
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        } catch (SocketTimeoutException e) {
            baseResData.setProcessing(true);
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        }catch (SocketException e) {
            baseResData.setRespMsg(e.getClass().getName().concat(" 异常描述:".concat(e.getMessage())));
        } catch (Exception e) {
            baseResData.setRespMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        } finally {
            try {
                if (httpEntity != null){
                    EntityUtils.consume(httpEntity);
                }
            } catch (IOException e) {
                LogPortal.error("{} {}http请求释放资源异常",e,traceId,methodDesc);
            }
        }
        //请求接口的响应时间
        endTime=System.currentTimeMillis();
        if ("互娱下单".equals(methodDesc)){
            if (StringUtils.isNotEmpty(result)){
                try {
                    JSONObject jsonObject =JSONObject.parseObject(result);
                    if ("5".equals(jsonObject.getString("datatype"))){
                        jsonObject.remove("data");
                    }
                    LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,jsonObject.toJSONString());
                } catch (Exception e) { }
            } else {
                LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,result);
            }
        } else {
            LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,result);
        }
        return baseResData;
    }

    public static CommonResult sendPostFormAyb(String traceId, String methodDesc, String url, Map<String, String> paramMap, int socketTimeoutSecond, CharSetEnum charSetEnum) {
        CommonResult commonResult= new CommonResult();
        commonResult.setCode(-1);
        //声明返回结果
        String result = "";
        //开始请求API接口时间
        long startTime=System.currentTimeMillis();
        //请求API接口的响应时间
        long endTime= 0L;
        int responseCode=-1;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = null;
        HttpEntity httpEntity = null;
        BaseResData baseResData = new BaseResData();
        try {
            // 设置链接超时等待时间
            if (socketTimeoutSecond ==0) { // 默认为2分钟
                socketTimeoutSecond = 120;
            }
            org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom().
                    setConnectTimeout(10 * 1000).
                    setConnectionRequestTimeout(10 * 1000).
                    setSocketTimeout(socketTimeoutSecond * 1000). //超时最大等待时间
                    build();
            // 创建连接
            if (url.startsWith("https")){
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setSSLSocketFactory(new SSLConnectionSocketFactory(getSslContext())).build();
            } else {
                httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
            }
            Charset charset = Charset.forName(CharSetUtil.getCharSet(charSetEnum));
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> nvps = new ArrayList<>();
            for (String key : paramMap.keySet()) {
                nvps.add(new BasicNameValuePair(key, paramMap.get(key)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps,charset));

           // LogPortal.info("{} {}请求开始 URL:{} {}",traceId,methodDesc,url,paramMap.get("legalIdCardProsFileByte").length());
            response = httpClient.execute(httpPost);
            responseCode = response.getStatusLine().getStatusCode();
            if (responseCode ==200){
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    commonResult=JsonUtils.fromJson(result,CommonResult.class);
                }
                if (StringUtils.isEmpty(result)){
                    commonResult.setCode(-1);
                    commonResult.setMsg("响应内容为空，错误码:"+traceId);
                }
            } else {
                commonResult.setCode(-1);
                commonResult.setMsg("请求错误:"+responseCode+"，错误码:"+traceId);
                httpEntity = response.getEntity();
                if (httpEntity != null) {
                    result = EntityUtils.toString(httpEntity,charset);
                    baseResData.setData(result);
                }
            }
        } catch (ConnectTimeoutException e) {
            commonResult.setMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        } catch (SocketTimeoutException e) {
            baseResData.setProcessing(true);
            commonResult.setMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        }catch (SocketException e) {
            commonResult.setMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        } catch (Exception e) {
            commonResult.setMsg("发生"+e.getClass().getName()+"异常，错误码:"+traceId);
            LogPortal.error("{} {}http请求发生{}异常",e,traceId,methodDesc,e.getClass().getName());
        } finally {
            try {
                if (httpEntity != null){
                    EntityUtils.consume(httpEntity);
                }
            } catch (IOException e) {
                LogPortal.error("{} {}http请求释放资源异常",e,traceId,methodDesc);
            }
        }
        //请求接口的响应时间
        endTime=System.currentTimeMillis();
        if (url.contains("/ayb-pay-api/v1/f/down_file")){
            LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:不打印",traceId,methodDesc,(endTime-startTime),responseCode);
        } else {
            LogPortal.info("{} {}耗时:{}ms httpStatus:{} 响应报文:{}",traceId,methodDesc,(endTime-startTime),responseCode,result);
        }
        return commonResult;
    }
}
